package heap

import (
	"jvm/classfile"
	. "jvm/typedef"
)

type ConstantPool struct {
	constants []Constant
	class     *Class
}
type Constant interface{}

func newConstantPool(class *Class, cfcp classfile.ConstantPool) *ConstantPool {
	length := len(cfcp)
	constants := make([]Constant, length)
	cp := &ConstantPool{
		class:     class,
		constants: constants,
	}
	for i := 1; i < length; i++ {
		cpInfo := cfcp[i]
		switch cpInfo.(type) {
		case *classfile.ConstantInteger:
			constants[i] = cpInfo.(*classfile.ConstantInteger).Val()
		case *classfile.ConstantLong:
			constants[i] = cpInfo.(*classfile.ConstantLong).Val()
			i++
		case *classfile.ConstantFloat:
			constants[i] = cpInfo.(*classfile.ConstantFloat).Val()
		case *classfile.ConstantDouble:
			constants[i] = cpInfo.(*classfile.ConstantDouble).Val()
			i++
		case *classfile.ConstantString:
			constants[i] = cpInfo.(*classfile.ConstantString).String()
		case *classfile.ConstantClass:
			constants[i] = newClassRef(cp, cpInfo.(*classfile.ConstantClass))
		case *classfile.ConstantFieldref:
			constants[i] = newFieldRef(cp, cpInfo.(*classfile.ConstantFieldref))
		case *classfile.ConstantMethodref:
			constants[i] = newMethodRef(cp, cpInfo.(*classfile.ConstantMethodref))
		case *classfile.ConstantInterfaceMethodref:
			constants[i] = newInterfaceMethodRef(cp, cpInfo.(*classfile.ConstantInterfaceMethodref))
		}
	}
	return cp
}

// **************************************************
// public
func (self *ConstantPool) GetConstant(index U2) Constant {
	if constat := self.constants[index]; constat != nil {
		return constat
	}
	return nil
}
